package com.fumasoft.dynamic;

import com.fumasoft.dynamic.utils.SpringContextUtil;
import com.puppycrawl.tools.checkstyle.Checker;
import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
import com.puppycrawl.tools.checkstyle.PropertiesExpander;
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.AuditListener;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 动态服务启动类.
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableAspectJAutoProxy
@MapperScan(basePackages = {"com.fumasoft.dynamic.server.mapper"})
@EnableFeignClients(basePackages = {"com.fumasoft"})
@Slf4j
public class DynamicServerApplication {

    /**
     * 启动方法.
     *
     * @param args 参数
     */
    public static void main(String[] args) throws Exception {

        // ======== 1. 校验 Checkstyle 必须校验,否则过不了jenkins构建=========
        validateCheckstyle();

        // ======== 2. 启动 Spring Boot =========
        ConfigurableApplicationContext applicationContext = SpringApplication.run(DynamicServerApplication.class, args);
        SpringContextUtil.setApplicationContext(applicationContext);
    }

    /**
     * 校验 Checkstyle.
     */
    private static void validateCheckstyle() throws Exception {
        // 加载 Checkstyle 配置文件
        Configuration config = ConfigurationLoader.loadConfiguration(
                "config/checkstyle.xml",
                new PropertiesExpander(System.getProperties())
        );

        Checker checker = new Checker();
        checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
        checker.configure(config);

        // 添加 AuditListener 打印详细错误信息
        checker.addListener(new AuditListener() {
            @Override
            public void auditStarted(AuditEvent event) { }

            @Override
            public void auditFinished(AuditEvent event) { }

            @Override
            public void fileStarted(AuditEvent event) { }

            @Override
            public void fileFinished(AuditEvent event) { }

            @Override
            public void addError(AuditEvent event) {
                // 打印错误文件、行号和具体信息
                System.err.printf("[%s:%d] %s%n",
                        event.getFileName(),
                        event.getLine(),
                        event.getMessage());
            }

            @Override
            public void addException(AuditEvent event, Throwable throwable) {
                System.err.printf("Exception in file %s: %s%n",
                        event.getFileName(), throwable.getMessage());
            }
        });

        Path srcPath = Paths.get(System.getProperty("user.dir"), "dynamic-server-web", "src", "main", "java");

        // 扫描 src/main/java 下所有 java 文件
        List<File> javaFiles = Files.walk(srcPath)
                .filter(Files::isRegularFile)
                .filter(p -> p.toString().endsWith(".java"))
                .map(Path::toFile)
                .collect(Collectors.toList());

        int errors = checker.process(javaFiles);
        checker.destroy();

        if (errors > 0) {
            throw new IllegalStateException("Checkstyle 校验失败，错误数量: " + errors + "，启动被阻止！");
        }
        log.info("Checkstyle 校验通过，继续启动应用");
    }
}